package middleware

import (
	"context"
	"fmt"
	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/aws/aws-sdk-go-v2/credentials"
	"github.com/aws/aws-sdk-go-v2/service/s3"
	"io"
	"log"
)

type FileManager interface {
	ListBuckets()
	ListObjects()
	UploadFile(fileName string, body io.Reader)
	DownloadFile(fileName string)
	DeleteFile(fileName string)
}
type MinioFileManager struct {
}

var client *s3.Client
var ctx context.Context

const (
	minioEndpoint = "http://192.168.56.141:9000" // MinIO 默认端口 9000
	accessKey     = "newuser"
	secretKey     = "newuserpassword"
	bucketName    = "mybucket"
	region        = "cq-local" // MinIO 需要指定区域，但可以是任意值
)

func (mfm MinioFileManager) ListBuckets() {
	result, err := client.ListBuckets(ctx, &s3.ListBucketsInput{})
	if err != nil {
		logger.Info(fmt.Sprintf("列出存储桶失败: %v", err))
		return
	}

	log.Println("可用的存储桶:")
	for _, bucket := range result.Buckets {
		logger.Info(fmt.Sprintf(" - %v (创建于: %v)", *bucket.Name, bucket.CreationDate))
	}
}

func init() {
	ctx = context.Background()
	customResolver := aws.EndpointResolverWithOptionsFunc(func(service, region string, options ...interface{}) (aws.Endpoint, error) {
		if service == s3.ServiceID {
			return aws.Endpoint{
				URL:               minioEndpoint,            // MinIO 地址
				HostnameImmutable: true,                     // 必须设置，MinIO 需要
				SigningRegion:     "cq-local",               // 任意有效区域
				Source:            aws.EndpointSourceCustom, // 标记为自定义端点
			}, nil
		}
		// 默认回退到 AWS 标准端点
		return aws.Endpoint{}, &aws.EndpointNotFoundError{}
	})

	// 2. 加载配置
	cfg, err := config.LoadDefaultConfig(ctx,
		config.WithRegion(region),
		config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(accessKey, secretKey, "")),
		config.WithEndpointResolverWithOptions(customResolver),
	)
	if err != nil {
		log.Fatalf("无法加载配置: %v", err)
	}

	// 3. 创建 S3 客户端
	client = s3.NewFromConfig(cfg, func(o *s3.Options) {
		o.UsePathStyle = true // MinIO 需要路径样式访问
		o.DisableLogOutputChecksumValidationSkipped = true
	})

}
func (mfm MinioFileManager) ListObjects() {
	result, err := client.ListObjectsV2(ctx, &s3.ListObjectsV2Input{
		Bucket: aws.String(bucketName),
	})
	if err != nil {
		logger.Info(fmt.Sprintf("列出对象失败: %v", err))
		return
	}

	logger.Info(fmt.Sprintf("存储桶 %v 中的对象:", bucketName))
	for _, item := range result.Contents {
		logger.Info(fmt.Sprintf(" - %v (大小: %v bytes, 最后修改: %v)", *item.Key, item.Size, item.LastModified))
	}
}

func (mfm MinioFileManager) UploadFile(fileName string, body io.Reader) {
	_, err := client.PutObject(ctx, &s3.PutObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(fileName),
		Body:   body,
	})
	if err != nil {
		logger.Info(fmt.Sprintf("上传文件失败: %v", err))

		return
	}

	logger.Info(fmt.Sprintf("成功上传文件: %v", fileName))
}

func (mfm MinioFileManager) DownloadFile(fileName string) {
	result, err := client.GetObject(ctx, &s3.GetObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(fileName),
	})
	if err != nil {
		logger.Info(fmt.Sprintf("下载文件失败: %v", err))
		return
	}
	defer result.Body.Close()
	//logger.Info(fmt.Sprintf("object: %v", result.Body))
	// 读取 Body 并转为字符串
	data, err := io.ReadAll(result.Body)
	if err != nil {
		logger.ERROR(fmt.Sprintf("读取文件内容失败: %v", err))
	}

	content := string(data)
	logger.Info(fmt.Sprintf("文件内容: %v", content))

}

func (mfm MinioFileManager) DeleteFile(fileName string) {
	_, err := client.DeleteObject(ctx, &s3.DeleteObjectInput{
		Bucket: aws.String(bucketName),
		Key:    aws.String(fileName),
	})
	if err != nil {
		logger.Info(fmt.Sprintf("删除文件失败: %v", err))
		return
	}

	logger.Info(fmt.Sprintf("成功删除文件: %v", fileName))
}
